查看原文
其他

x32下逆向分析PsSetCreateProcessNotifyRoutine

张新琪 看雪学院 2019-09-17

本文为看雪论坛优秀文章

看雪论坛作者ID:张新琪



前言



本文记录一下自己的分析思路以及逆向结果。
 
内核中 PsSetCreateProcessNotifyRoutine 回调函数是用来设置进程监控的。相应的还有一个ex函数,ex函数没有逆向。

这里简单说一下进程回调的逆向。


逆向过程



>>>>

windbg挂载 win7 32位.定位到函数反汇编


定位反汇编代码如下:

kd> uf PsSetCreateProcessNotifyRoutine
nt!PsSetCreateProcessNotifyRoutine:
83fd87de 8bff mov edi,edi
83fd87e0 55 push ebp
83fd87e1 8bec mov ebp,esp
83fd87e3 6a00 push 0
83fd87e5 ff750c push dword ptr [ebp+0Ch] 参数2 ---------> 是否删除
83fd87e8 ff7508 push dword ptr [ebp+8] 参数1 ---------> 回调函数地址
83fd87eb e809000000 call nt!PspSetCreateProcessNotifyRoutine (83fd87f9)
83fd87f0 5d pop ebp
83fd87f1 c20800 ret 8

可以看到里面调用的函数为: PspSetCreateProcessNotifyRoutine。

总共三个参数
 
伪代码
 
PspSetCreateProcessNotifyRoutine(0,你自己的回调函数地址,是否删除标记)
 
而逆向Ex系列的函数,发现变得仅仅是第一个函数参数, 0变为1了。



>>>>

逆向 PspSetCreateProcessNotifyRoutine


底层函数调用的它,那么就逆向它。

kd> uf PspSetCreateProcessNotifyRoutine
nt!PspSetCreateProcessNotifyRoutine:
83fd87f9 8bff mov edi,edi
83fd87fb 55 push ebp
83fd87fc 8bec mov ebp,esp
83fd87fe 807d0c00 cmp byte ptr [ebp+0Ch],0 //判断是设置回调还是清除回调.

83fd8802 53 push ebx
83fd8803 56 push esi //保存寄存器环境.
83fd8804 57 push edi

83fd8805 0f84fa000000 je nt!PspSetCreateProcessNotifyRoutine+0x10a (83fd8905) 是否删除回调 == 0 跳转.也就是设置回调. 删除回调走上边.

====================> 删除回调走的位置

nt!PspSetCreateProcessNotifyRoutine+0x12:
83fd880b 648b3524010000 mov esi,dword ptr fs:[124h]
83fd8812 66ff8e84000000 dec word ptr [esi+84h]
83fd8819 33db xor ebx,ebx
83fd881b c7450ce06cf883 mov dword ptr [ebp+0Ch],offset nt!PspCreateProcessNotifyRoutine (83f86ce0) //获得回调函数数组地址.

nt!PspSetCreateProcessNotifyRoutine+0x29:
83fd8822 ff750c push dword ptr [ebp+0Ch] //数组地址压栈.
83fd8825 e88ea90d00 call nt!ExReferenceCallBackBlock (840b31b8) //逆向ExReferenceCallBackBlock
83fd882a 8bf8 mov edi,eax
83fd882c 85ff test edi,edi
83fd882e 7439 je nt!PspSetCreateProcessNotifyRoutine+0x6e (83fd8869)

nt!PspSetCreateProcessNotifyRoutine+0x37:
83fd8830 8b4f08 mov ecx,dword ptr [edi+8]
83fd8833 e81b3cf2ff call nt!ExGetCallBackBlockRoutine (83efc453)
83fd8838 3b4508 cmp eax,dword ptr [ebp+8]
83fd883b 7522 jne nt!PspSetCreateProcessNotifyRoutine+0x64 (83fd885f)

nt!PspSetCreateProcessNotifyRoutine+0x44:
83fd883d 85c9 test ecx,ecx
83fd883f 7509 jne nt!PspSetCreateProcessNotifyRoutine+0x4f (83fd884a)

......由于代码过长,此处仅放部分代码,更多请点击阅读原文查看

通过上面可以看到获得的回调函数数组,并且函数数组入栈。那么就需要逆向一下新的函数了。
 
首先看下回调函数数组里面的内容:


83f86ce0 = 回调函数数组



找到回调函数数组会发现这个值不是回调函数地址。

下面回调 ExReferenceCallBackBlock 传入回调函数地址,所以肯定有对 其的操作。


>>>>

逆向 ExReferenceCallBackBlock


kd> uf ExReferenceCallBackBlock
nt!ExReferenceCallBackBlock:
840b31b8 8bff mov edi,edi
840b31ba 55 push ebp
840b31bb 8bec mov ebp,esp
840b31bd 8b5508 mov edx,dword ptr [ebp+8] edx = 数组地址
840b31c0 8b0a mov ecx,dword ptr [edx] ecx = 数组[0] 第一项.

840b31c2 53 push ebx
840b31c3 56 push esi
840b31c4 57 push edi
840b31c5 6a07 push 7
840b31c7 5b pop ebx ebx = 7
840b31c8 84cb test bl,cl 判断bl 跟 cl 肯定不等于 0 .

840b31ca 7417 je nt!ExReferenceCallBackBlock+0x2b (840b31e3)

// bl cl 不会 = 0,所以走此位置.

......由于代码过长,此处仅放部分代码,更多请点击阅读原文查看


通过逆向次函数可以得知函数数组[0]的内容被修改了, 修改为 -1的值, 如上面看到的数组的内容为:
 

现在首内容 0x8d408c3f的值会变为 0x8d408c3e

往下有很多分支没有走,最后会进行解密操作得出函数地址。
 
如: 0x8d408c3e & 0xFFFFFFF8 = 函数地址表。

如下:

 
 
这个函数地址表的第二项就是我们要找的函数地址。
 
现在是0x83f01d35 pchunter中查看。


但是上面会有一个问题,0x8d408c3f的值会变为 0x8d408c3e 直接用 0x8d408c3f & 0xFFFFFFF8 的结果也是一样的。

所以可以忽略上面修改值的事情。
 
可以得出一个公式 函数地址 = *((数组[n] & 0xFFFFFFF8) + 4)
 
可以套用一下公式,进行一次计算。


使用代码可以遍历出函数地址表,表中第二项才是函数地址。随便找一个举例:
 
 
它的第二项是8c5f89d8 说明找对了。


总结



通过逆向可以找到数组,那么可以进行如下操作:
 
1. 摘除数组,传入函数地址。调用 PsSetCreateProcessNotifyRoutine 第二个参数为TRUE即可摘掉,你也可以自己摘,就是相当于自己实现了一下这个函数摘除钩子的代码。

2. 进程回调优先级,可以找到数组,将你的回调写入到数组第一项,这样你的就会优先到来。这个没试过,算是一个思路吧。




- End -




看雪ID:张新琪 

https://bbs.pediy.com/user-723188.htm  


*本文由看雪论坛 张新琪 原创,转载请注明来自看雪社区



往期热门回顾

1、C++中基本数据类型的表现形式

2、【Android改机系列】全息备份原理剖析

3、【Android改机系列】一键新机原理剖析

4、KCTF 晋级赛Q3「防守篇」来了!最全参赛指南看这里

5、密码学基础:Base64编码







公众号ID:ikanxue

官方微博:看雪安全

商务合作:wsc@kanxue.com




      ↙点击下方“阅读原文”,查看更多干货

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存